#
# Copyright (C) 2015 - 2020, IBEROXARXA SERVICIOS INTEGRALES, S.L.
# Copyright (C) 2015 - 2020, Jaume Olive Petrus (jolive@whitecatboard.org)
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#    # Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#    # Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#    # Neither the name of the <organization> nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#    # The WHITECAT logotype cannot be changed, you can remove it, but you
#       cannot change it in any way. The WHITECAT logotype is:
#
#          /\       /\
#         /  \_____/  \
#        /_____________\
#        W H I T E C A T
#
#    # Redistributions in binary form must retain all copyright notices printed
#       to any local or remote output device. This include any reference to
#       Lua RTOS, whitecatboard.org, Lua, and other copyright notices that may
#       appear in the future.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

# This script generates all the necessary configuration files to build and
# register the boards supported by the Whitecat Ecosystem.
#
# The script takes the following input files:
#
# * boards/supported_boards.json: a JSON file that describes the supported
#   boards and the firmwares available for each board.
#
# * boards/boards_compat.json: a JSON file that describes some required
#   information to maintain backward copmpatibility with older Lua RTOS
#   firmwares, the wcc tool, and The Whitecat IDE.
#
#   DO NOT EDIT THIS FILE!! 
#
# The script generates the following configuration files:
#
# * components/sys/firmwares.h: a C header file required to build Lua RTOS
#.  for each supported firmware.
#
#   DO NOT EDIT THIS FILE!! 
#
# * components/sys/Kconfig: a modification of the original components/sys/Kconfig
#.  that includes a selection option for each supported firmware.
#
#   DO NOT EDIT THIS FILE!! 
#
# * boards/boards.json: a configuration file to maintain backward copmpatibility
#   with the wcc tool and the Whitecat IDE.

import json
import sys
import shutil
import os

included_firmwares = []

# Read JSON configuration files. If an error is raised exit immediately
with open("boards/boards_compat.json") as json_data:
    try:
        compat = json.load(json_data)
    except:
        print "Error reading boards/boards_compat.json: %s" % (sys.exc_info()[1])
        exit(1)

    json_data.close()

with open("boards/supported_boards.json") as json_data:
    try:
        boards = json.load(json_data)
    except:
        print "Error reading boards/supported_boards.json: %s" % (sys.exc_info()[1])
        exit(1)
    
    json_data.close()

# Create components/sys/firmwares.h.new file
includef = open("components/sys/firmwares.h.new","w")

# Create boards/boards.json.new file
boardsf = open("boards/boards.json.new","w")

# Create components/sys/Kconfig.new file
kconfigf = open("components/sys/Kconfig.new","w")

# Start generating the new Kconfig file. In this step we copy the content of the 
# components/sys/Kconfig file to components/sys/Kconfig.new file from the
# beginning of the firmware options.
with open("components/sys/Kconfig") as kconfig_data:
    kconfig = kconfig_data.readlines()
    
for line in kconfig:
    if "default LUA_RTOS_FIRMWARE_WHITECAT_ESP32_N1" in line:
        kconfigf.write(line)
        kconfigf.write("\r\n")
        break
        
    kconfigf.write(line)

# Generation of components/sys/firmwares.h file, and insertion of configuration
# options in components/sys/Kconfig
includef.write("#ifndef LUA_RTOS_FIRMWARES_H_\r\n")
includef.write("#define LUA_RTOS_FIRMWARES_H_\r\n\r\n")

for i, board in enumerate(boards, 1):
    for j, firmware in enumerate(board["firmwares"], 1):
        # Check that firmware if is unique
        if firmware["id"] not in included_firmwares:
            included_firmwares.append(firmware["id"])
            
            includef.write('#if CONFIG_LUA_RTOS_FIRMWARE_%s\r\n' % (firmware["id"].replace("-","_")))
            includef.write('#define CONFIG_LUA_RTOS_FIRMWARE \"%s\"\r\n' % (firmware["id"]))
            
            has_compat_data = 0
            
            for k, compat_data in enumerate(compat, 1):
                if compat_data["id"] == firmware["id"]:
                    includef.write('#define CONFIG_LUA_RTOS_BOARD_TYPE \"%s\"\r\n' % (compat_data["type"]))
                    includef.write('#define CONFIG_LUA_RTOS_BOARD_SUBTYPE \"%s\"\r\n' % (compat_data["subtype"]))
                    
                    has_compat_data = 1
                    break
                    
            if has_compat_data == 0:
                includef.write('#define CONFIG_LUA_RTOS_BOARD_TYPE \"%s\"\r\n' % (firmware["id"]))
                includef.write('#define CONFIG_LUA_RTOS_BOARD_SUBTYPE \"\"\r\n')                
            
            includef.write('#endif\r\n\r\n')
        
            kconfigf.write("      config LUA_RTOS_FIRMWARE_%s\r\n" % (firmware["id"].replace("-","_")))
            kconfigf.write("         bool \"%s\"\r\n\r\n" % (firmware["description"]))
        else:
            print "Duplicated firmware id %s" % (firmware["id"])
            exit(1)
            
includef.write("#endif")

# Copy the content of the components/sys/Kconfig file to components/sys/Kconfig.new file from the
# end of the firmware options until the end of file.
skip_board_type = 0

for line in kconfig:        
    if skip_board_type == 0:
        if "default LUA_RTOS_FIRMWARE_WHITECAT_ESP32_N1" in line:
            skip_board_type = 1
            
    if skip_board_type == 1:
        if "endchoice" in line:
            skip_board_type = 2

    if skip_board_type == 2:
        kconfigf.write(line)
   
# Generate boards/boards.json
first = 1
boardsf.write("[\r\n")

for i, board in enumerate(boards, 1):
    for j, firmware in enumerate(board["firmwares"], 1):
        has_compat_data = 0
        
        for k, compat_data in enumerate(compat, 1):
            if compat_data["id"] == firmware["id"]:
                if first == 0:
                    boardsf.write("    },\r\n")
                    
                boardsf.write("    {\r\n")
                boardsf.write("        \"id\": \"%s\",\r\n" % (firmware["id"]))
                boardsf.write("        \"description\": \"%s\",\r\n" % (firmware["description"]))
                boardsf.write("        \"manufacturer\": \"%s\",\r\n" % (board["manufacturer"]))
                boardsf.write("        \"brand\": \"\",\r\n")
                boardsf.write("        \"type\": \"%s\",\r\n" % (compat_data["type"]))
                boardsf.write("        \"subtype\": \"%s\",\r\n" % (compat_data["subtype"])) 
                boardsf.write("        \"filesystem\": \"%s\",\r\n" % (firmware["filesystem"]))
                boardsf.write("        \"usb_vid_pid\": \"%s\",\r\n" % (board["usb_vid_pid"]))
                boardsf.write("        \"usb_port_exp\": \"%s\",\r\n" % (board["usb_port_exp"]))
                boardsf.write("        \"image\": \"%s\"\r\n" % (board["image"]))
                
                first = 0
                has_compat_data = 1
                break
                
        if has_compat_data == 0:
            if first == 0:
                boardsf.write("    },\r\n")
                
            boardsf.write("    {\r\n")
            boardsf.write("        \"id\": \"%s\",\r\n" % (firmware["id"]))
            boardsf.write("        \"description\": \"%s\",\r\n" % (firmware["description"]))
            boardsf.write("        \"manufacturer\": \"%s\",\r\n" % (board["manufacturer"]))
            boardsf.write("        \"brand\": \"\",\r\n")
            boardsf.write("        \"type\": \"%s\",\r\n" % (firmware["id"]))
            boardsf.write("        \"subtype\": \"\",\r\n") 
            boardsf.write("        \"filesystem\": \"%s\",\r\n" % (firmware["filesystem"]))
            boardsf.write("        \"usb_vid_pid\": \"%s\",\r\n" % (board["usb_vid_pid"]))
            boardsf.write("        \"usb_port_exp\": \"%s\",\r\n" % (board["usb_port_exp"]))
            boardsf.write("        \"image\": \"%s\"\r\n" % (board["image"]))
            
            first = 0
            
boardsf.write("    }\r\n")
boardsf.write("]")

boardsf.flush()
includef.flush()
kconfigf.flush()

boardsf.close()
includef.close()
kconfigf.close()

shutil.copy2("components/sys/firmwares.h.new", "components/sys/firmwares.h")
os.remove("components/sys/firmwares.h.new")   

shutil.copy2("boards/boards.json.new", "boards/boards.json")
os.remove("boards/boards.json.new")   

shutil.copy2("components/sys/Kconfig.new", "components/sys/Kconfig")
os.remove("components/sys/Kconfig.new")